package org.budo.graph.service.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.math.NumberUtils;
import org.budo.support.java.io.util.RandomAccessFileUtil;
import org.budo.support.lang.util.FileUtil;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.ListUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.servlet.util.QueryStringUtil;

/**
 * @author limingwei
 * @date 2016年6月14日 下午8:36:39
 */
public class FileExplorerUtil {
    public static final String AFTER_FILE_INDEX = "<!--AfterFileIndex-->";

    public static String writeFileExplorerResponse(String url) {
        Map<String, String> parameters = QueryStringUtil.queryStringToStringMap(url);
        String path = parameters.get("_");

        File currentFile;
        if (null == path || path.trim().isEmpty()) {
            return writeRoot();
        }

        currentFile = new File(path);
        if (!currentFile.exists()) {
            return withHtml("#37 file not exists");
        }

        if (currentFile.isDirectory()) {
            return writeDir(currentFile);
        }

        if (StringUtil.equalsIgnoreCase("true", parameters.get("download"))) {
            return writeDownloadFile(currentFile, parameters);
        }

        return writeFile(currentFile, parameters);
    }

    public static String writeRoot() {
        return writeDirAndSub(null, File.listRoots());
    }

    private static String writeDownloadFile(File currentFile, Map<String, String> parameters) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        IoUtil.write(IoUtil.fileInputStream(currentFile), byteArrayOutputStream);
        return new String(byteArrayOutputStream.toByteArray());
    }

    public static String writeFile(File currentFile, Map<String, String> parameters) {
        String result = "";

        String seekStr = parameters.get("seek");
        String limitStr = parameters.get("limit");

        int limit = NumberUtils.toInt(limitStr, 100);
        long seek = NumberUtils.toLong(seekStr, 0);

        if (seek < 0) {
            seek = 0;
        }

        if (limit < 10) {
            limit = 10;
        }

        if (limit > 2000) {
            limit = 2000;
        }

        RandomAccessFile randomAccessFile = FileUtil.newRandomAccessFile(currentFile, "r");
        RandomAccessFileUtil.seek(randomAccessFile, seek);
        String line;
        String logLines = "";
        for (int i = 0; i < limit && (line = RandomAccessFileUtil.readLine(randomAccessFile)) != null; i++) {
            logLines += StringUtil.changeCharset(line, "ISO-8859-1", "UTF-8") + "\n";
        }

        int logLinesLength = logLines.length();

        result += writeIndex(currentFile) + "&nbsp;";

        result += "<a target=\"_blank\" href=\"file-explorer?_=" + FileUtil.getCanonicalPath(currentFile) + "&download=true" + "\">下载</a>&nbsp;";
        result += "<a href=\"file-explorer?_=" + FileUtil.getCanonicalPath(currentFile) + "&seek=0&limit=" + limit + "\">第一页</a>&nbsp;";
        result += "<a href=\"file-explorer?_=" + FileUtil.getCanonicalPath(currentFile) + "&seek=" + (seek - (logLinesLength < 1 ? 100 : logLinesLength)) + "&limit=" + limit + "\">上一页</a>&nbsp;";
        result += "<a href=\"file-explorer?_=" + FileUtil.getCanonicalPath(currentFile) + "&seek=" + (seek + logLinesLength) + "&limit=" + limit + "\">下一页</a>&nbsp;";
        result += "<a href=\"file-explorer?_=" + FileUtil.getCanonicalPath(currentFile) + "&seek=" + (currentFile.length() - 8000) + "\">最后一页</a>&nbsp;";
        result += "<br/>";
        result += "<pre class=\"brush: java;\">" + logLines + "</pre>";
        RandomAccessFileUtil.close(randomAccessFile);

        return withHtml(result);
    }

    public static String withHtml(String result) {
        return "<html><head>" //
                + "<script type=\"text/javascript\" src=\"js/syntaxhighlighter-shCore.js\"></script>" //
                + "<script type=\"text/javascript\" src=\"js/syntaxhighlighter-shBrushJava.js\"></script>" //
                + "<link type=\"text/css\" rel=\"stylesheet\" href=\"css/syntaxhighlighter-shCoreEclipse.css\"/>" //
                + "<script type=\"text/javascript\">SyntaxHighlighter.all();</script>" //
                + "</head>" + result + "</html>";
    }

    public static String writeDir(File currentFile) {
        return writeDirAndSub(currentFile, currentFile.listFiles());
    }

    private static String writeDirAndSub(File currentFile, File[] subFiles) {
        String result = "";
        result += writeIndex(currentFile);
        result += "<hr/>";

        if (null != subFiles && subFiles.length > 0) {
            result += "<ol>";
            List<File> list = ListUtil.toList(subFiles);
            Collections.sort(list); // 排序
            for (File file : list) {
                result += "<li>";
                result += "<a href=\"file-explorer?_=" + FileUtil.getCanonicalPath(file) + "\">" + FileUtil.getCanonicalPath(file) + "</a>";
                result += "&nbsp;&nbsp;" + file.length();
                result += "<br/>";
                result += "</li>";
            }
            result += "</ol>";
        }
        return withHtml(result);
    }

    private static String writeIndex(File currentFile) {
        String result = "";
        result += "<a href=\"file-explorer\">Root</a> ";

        if (null != currentFile) {
            List<File> parentFiles = new ArrayList<File>();
            parentFiles.add(currentFile);
            for (;;) {
                File f = currentFile.getParentFile();
                if (null != f) {
                    parentFiles.add(f);
                    currentFile = f;
                } else {
                    break;
                }
            }

            for (int i = parentFiles.size() - 1; i >= 0; i--) {
                File file = parentFiles.get(i);
                String name = file.getName();
                if (null == name || name.trim().isEmpty()) {
                    name = file.getPath();
                }
                result += "<a href=\"file-explorer?_=" + file.getPath() + "\">" + name + "</a> ";
            }
        }
        result += AFTER_FILE_INDEX;
        return result;
    }
}
